package com.qiaoba.module.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.dto.SysRoleDTO;
import com.qiaoba.common.base.exception.ServiceException;
import com.qiaoba.module.system.converter.SysRoleConverter;
import com.qiaoba.module.system.entity.SysRole;
import com.qiaoba.module.system.entity.SysRoleDept;
import com.qiaoba.module.system.entity.dto.DataScopeDTO;
import com.qiaoba.module.system.entity.param.SysRoleParam;
import com.qiaoba.module.system.mapper.SysRoleMapper;
import com.qiaoba.module.system.service.SysRoleDeptService;
import com.qiaoba.module.system.service.SysRoleMenuService;
import com.qiaoba.module.system.service.SysRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 角色 服务层实现
 *
 * @author ailanyin
 * @date 2023-09-10 14:03:47
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {

    private final SysRoleMapper sysRoleMapper;
    private final SysRoleMenuService sysRoleMenuService;
    private final SysRoleDeptService sysRoleDeptService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDataScope(DataScopeDTO dto) {
        // 更新信息
        SysRole sysRole = SysRoleConverter.dto2Entity(dto);
        int row = sysRoleMapper.updateById(sysRole);
        // 删除绑定
        sysRoleDeptService.deleteByRoleIds(CollUtil.toList(sysRole.getRoleId()));
        // 新增绑定
        if (CollUtil.isNotEmpty(dto.getDeptIds())) {
            List<SysRoleDept> list = new ArrayList<>();
            for (String deptId : dto.getDeptIds()) {
                list.add(new SysRoleDept(dto.getRoleId(), deptId));
            }
            sysRoleDeptService.insertBatch(list);
        }

        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SysRoleDTO dto) {
        checkRoleNameUnique(dto.getRoleId(), dto.getRoleName());
        checkRoleKeyUnique(dto.getRoleId(), dto.getRoleKey());
        SysRole sysRole = SysRoleConverter.dto2Entity(dto);
        int result = sysRoleMapper.insert(sysRole);
        if (result > 0) {
            sysRoleMenuService.updateRoleMenu(sysRole.getRoleId(), dto.getMenuIds());
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SysRoleDTO dto) {
        checkRoleNameUnique(dto.getRoleId(), dto.getRoleName());
        // 业务上不允许更改key
        dto.setRoleKey(null);
        SysRole sysRole = SysRoleConverter.dto2Entity(dto);
        int result = sysRoleMapper.updateById(sysRole);
        if (result > 0) {
            sysRoleMenuService.updateRoleMenu(sysRole.getRoleId(), dto.getMenuIds());
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(String roleId) {
        return deleteByIds(CollUtil.toList(roleId));
    }

    @Override
    public int changeStatus(String roleId, String status) {
        SysRole sysRole = new SysRole();
        sysRole.setRoleId(roleId);
        sysRole.setStatus(status);
        return sysRoleMapper.updateById(sysRole);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(List<String> ids) {
        // 检查是否有绑定用户
        checkAllowDelete(ids);
        // 删除角色的部门数据权限
        sysRoleDeptService.deleteByRoleIds(ids);
        // 删除角色绑定的菜单权限
        sysRoleMenuService.deleteByRoleIds(ids);
        // 删除角色
        return sysRoleMapper.deleteBatchIds(ids);
    }

    @Override
    public SysRole selectById(String roleId, boolean allowNull) {
        SysRole sysRole = sysRoleMapper.selectById(roleId);
        if (!allowNull && Objects.isNull(sysRole)) {
            throw new ServiceException(StrUtil.format("查询角色不存在, ID: {}", roleId));
        }
        return sysRole;
    }

    @Override
    public List<SysRole> selectList(SysRoleParam param) {
        return sysRoleMapper.selectList(SysRoleConverter.param2Wrapper(param));
    }

    private void checkRoleNameUnique(String roleId, String roleName) {
        if (StrUtil.isNotBlank(sysRoleMapper.checkRoleNameUnique(roleId, roleName))) {
            throw new ServiceException(StrUtil.format("保存角色【{}】失败, 角色名称已存在", roleName));
        }
    }

    private void checkRoleKeyUnique(String roleId, String roleKey) {
        if (StrUtil.isNotBlank(sysRoleMapper.checkRoleKeyUnique(roleId, roleKey))) {
            throw new ServiceException(StrUtil.format("保存角色【{}】失败, 角色标识已存在", roleKey));
        }
    }

    private void checkAllowDelete(List<String> ids) {
        String user = sysRoleMapper.selectBindUserByRoleId(ids);
        if (StrUtil.isNotBlank(user)) {
            throw new ServiceException(StrUtil.format("删除角色失败，已绑定用户: {}", user));
        }
    }

}
